﻿using System;
using System.IO;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using XNADota.Input;

namespace XNADota
{
    /// <summary>
    /// Screenshot capturer grabbed from Racing Game
    /// </summary>
    public partial class ScreenCapturer : XNADotaObject, IInputHandler
    {
        const string ScreenshotsDirectory = "Screenshots";

        #region Variables
        /// <summary>
        /// Internal screenshot number (will increase by one each screenshot)
        /// </summary>
        private int screenshotNum = 0;
        /// <summary>
        /// If it's true, the Game should call TakeScreenshot at the end of the frame
        /// </summary>
        bool shouldCapture;

        public bool ShouldCapture
        {
            get { return shouldCapture; }
            set { shouldCapture = value; }
        }

        public Texture2D Screenshot
        {
            get
            {
                if (screenshot == null)
                {
                    screenshot = new ResolveTexture2D(
                        Game.GraphicsDevice,
                        Game.GraphicsDevice.Viewport.Width, Game.GraphicsDevice.Viewport.Height, 1,
                        SurfaceFormat.Color);

                    // Get data with help of the resolve method
                    Game.GraphicsDevice.ResolveBackBuffer(screenshot);
                }

                return screenshot;
            }
        }

        ResolveTexture2D screenshot;
        #endregion

        #region Constructor
        public ScreenCapturer(XNADota setGame)
            : base(setGame)
        {
            screenshotNum = GetCurrentScreenshotNum();
        }
        #endregion

        #region Make screenshot
        #region Screenshot name builder
        /// <summary>
        /// Screenshot name builder
        /// </summary>
        /// <param name="num">Num</param>
        /// <returns>String</returns>
        private string ScreenshotNameBuilder(int num)
        {
            return ScreenshotsDirectory + "/" +
                Game.Window.Title + " Screenshot " +
                num.ToString("0000") + ".jpg";
        }
        #endregion

        #region Get current screenshot num
        /// <summary>
        /// Get current screenshot num
        /// </summary>
        /// <returns>Int</returns>
        private int GetCurrentScreenshotNum()
        {
            // We must search for last screenshot we can found in list using own
            // fast filesearch
            int i = 0, j = 0, k = 0, l = -1;
            // First check if at least 1 screenshot exist
            if (File.Exists(ScreenshotNameBuilder(0)) == true)
            {
                // First scan for screenshot num/1000
                for (i = 1; i < 10; i++)
                {
                    if (File.Exists(ScreenshotNameBuilder(i * 1000)) == false)
                        break;
                }

                // This i*1000 does not exist, continue scan next level
                // screenshotnr/100
                i--;
                for (j = 1; j < 10; j++)
                {
                    if (File.Exists(ScreenshotNameBuilder(i * 1000 + j * 100)) == false)
                        break;
                }

                // This i*1000+j*100 does not exist, continue scan next level
                // screenshotnr/10
                j--;
                for (k = 1; k < 10; k++)
                {
                    if (File.Exists(ScreenshotNameBuilder(
                            i * 1000 + j * 100 + k * 10)) == false)
                        break;
                }

                // This i*1000+j*100+k*10 does not exist, continue scan next level
                // screenshotnr/1
                k--;
                for (l = 1; l < 10; l++)
                {
                    if (File.Exists(ScreenshotNameBuilder(
                            i * 1000 + j * 100 + k * 10 + l)) == false)
                        break;
                }

                // This i*1000+j*100+k*10+l does not exist, we have now last
                // screenshot nr!!!
                l--;
            }

            return i * 1000 + j * 100 + k * 10 + l;
        }
        #endregion

        public void TakeScreenshot()
        {
            try
            {
                //NOTE: This doesn't always work on all cards, especially if
                // desktop mode switches in fullscreen mode!

                screenshotNum++;
                // Make sure screenshots directory exists
                if (Directory.Exists(ScreenshotsDirectory) == false)
                    Directory.CreateDirectory(ScreenshotsDirectory);

                using (ResolveTexture2D dstTexture = new ResolveTexture2D(
                    Game.GraphicsDevice,
                    Game.GraphicsDevice.Viewport.Width, Game.GraphicsDevice.Viewport.Height, 1,
                    SurfaceFormat.Color))
                {
                    // Get data with help of the resolve method
                    Game.GraphicsDevice.ResolveBackBuffer(dstTexture);

                    dstTexture.Save(
                        ScreenshotNameBuilder(screenshotNum),
                        ImageFileFormat.Jpg);
                }
            }
            catch (Exception ex)
            {
            }
            finally
            {
                shouldCapture = false;
            }
        }

        public virtual void ProcessInput(GameTime gameTime, InputState inputState)
        {
            if (inputState.IsKeyJustDown(Keys.Q))
                this.TakeScreenshot();
        }
        #endregion
    }
}
